﻿/*
 * Armen Kirakosyan, 2012
 */

namespace FileStrider
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    using System.Threading;
    using System.Windows;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        #region Properties

        private Thread _walkerThread;

        public bool IsScanning { get; set; }
        public static string ApplicationName
        {
            get { return "FileStrider"; }
        }
        public static string Version
        {
            get
            {
                Assembly asm = Assembly.GetExecutingAssembly();
                FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);
                return String.Format("{0}.{1}", fvi.FileMajorPart, fvi.FileMinorPart);
            }
        }

        private string _winDir = Environment.GetEnvironmentVariable("windir").ToLowerInvariant();
        private string _skipDir = "";
        #endregion

        public MainWindow()
        {
            InitializeComponent();

            // Set main window title
            Title = ApplicationName + " v" + Version;

            // Localize interface
            ButtonDriveListRefresh.Content = "Refresh";
            ButtonAbout.Content = "About " + ApplicationName;

            LabelDrives.Content = "Drives";

            // Load drives list
            LoadDrives();

            CheckBoxSkipSystem.Content = "Skip " + _winDir;

            IsScanning = false;
        }

        void LoadDrives()
        {
            ListBoxDisks.Items.Clear();
            foreach (var drive in System.IO.DriveInfo.GetDrives())
            {
                var d = new ListItemDrive(drive.Name);
                d.ToolTip = new DriveTooltip(drive.Name);
                ListBoxDisks.Items.Add(d);
            }
        }

        private void ButtonDriveListRefresh_Click(object sender, RoutedEventArgs e)
        {
            LoadDrives();
        }

        private void ButtonStart_Click(object sender, RoutedEventArgs e)
        {
            if (IsScanning)
            {
                StopScan();
            }
            else
            {
                StartScan();
            }
        }

        void StartScan()
        {
            // Check if there is a selected drive
            List<ListItemDrive> drivesToScan = new List<ListItemDrive>();
            foreach (ListItemDrive drive in ListBoxDisks.Items)
            {
                if (drive.IsSelected != null && (bool)drive.IsSelected)
                {
                    drive.ResetProgress();
                    drivesToScan.Add(drive);
                }
            }
            if (drivesToScan.Count == 0)
            {
                MessageBox.Show("Please select drive",
                                "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            ButtonStart.Content = "Stop";
            IsScanning = true;
            FactsDs.Folders = new FactsDs.FactsDataTable();
            FactsDs.Files   = new FactsDs.FactsDataTable();
            FactsDs.SmallestFileSize = 0;
            FactsDs.SmallestFolderSize = 0;

            ListBoxBigFiles.Items.Clear();
            ListBoxBigFolders.Items.Clear();

            _skipDir = (bool)CheckBoxSkipSystem.IsChecked ? _winDir : "";

            _walkerThread = new Thread(new ParameterizedThreadStart(WalkAsync));
            _walkerThread.Start(drivesToScan);
        }
        private void WalkAsync(object folders)
        {
            List<ListItemDrive> drivesToScan = (List<ListItemDrive>)folders;
            foreach (var drive in drivesToScan)
            {
                Walk(drive, drive.DriveName);
                drive.ResetProgress();
            }
            StopScan();
        }
        private void Walk(ListItemDrive listItem, string folder)
        {
            DirectoryInfo f = new DirectoryInfo(folder);
            long folderSize = Helper.GetFolderSize(f.FullName, false);
            FactsDs.CheckFolderSize(f.FullName, folderSize);
            listItem.Progress(folderSize);

            // scan all folders
            foreach (DirectoryInfo di in f.GetDirectories())
            {
                if ( _skipDir != "" && di.FullName.ToLowerInvariant() == _winDir)
                {
                    continue;
                }

                try
                {
                    Walk(listItem, di.FullName);
                }
                catch (Exception exception) // yes, it happens if folder is secured
                {
#if DEBUG
                    Debug.WriteLine(exception.Message);
#endif
                }
            }

            // scan all files
            foreach (FileInfo file in f.GetFiles())
            {
                FactsDs.CheckFileSize(file);
            }
        }
        void StopScan()
        {
            IsScanning = false;
            Dispatcher.Invoke((Action)delegate
            {
                ButtonStart.Content = "Start";
                var facts = new FactsDs();
                int i = FactsDs.ShowFoldersInReport;

                // add items to folders list
                foreach (FactsDs.FactsRow row in FactsDs.SortFolders())
                {
                    ListBoxBigFolders.Items.Add(new ListItemFolder(row.EntityName,
                                                                   row.Size));

                    // add to dataset to send to report
                    if (i > 0)
                    {
                        var d = new DirectoryInfo(row.EntityName);
                        facts._Facts.Rows.Add(row.EntityName, row.Size, d.Name);
                        i--;
                    }
                }

                // add items to files list
                foreach (FactsDs.FactsRow row in FactsDs.SortFiles())
                {
                    ListBoxBigFiles.Items.Add(new ListItemFile(row.EntityName));
                }

                
            });
            MessageBox.Show("Done!", "", MessageBoxButton.OK,
                            MessageBoxImage.Exclamation);
            if (_walkerThread.IsAlive)
            {
                _walkerThread.Abort();
            }
        }

        private void ButtonAbout_Click(object sender, RoutedEventArgs e)
        {

        }

        private void ListBoxBigFolders_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (ListBoxBigFolders.SelectedItems.Count == 0) return;
            ListItemFolder folder = (ListItemFolder)ListBoxBigFolders.SelectedItems[0];
            System.Diagnostics.Process.Start(folder.FolderInfo.FullName);
        }

        private void ListBoxBigFiles_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (ListBoxBigFiles.SelectedItems.Count == 0) return;
            ListItemFile file = (ListItemFile)ListBoxBigFiles.SelectedItems[0];
            // open folder with selected file
            System.Diagnostics.Process.Start("explorer.exe", "/select, " + file.File.FullName);
        }
    }
}
